/**
 * Saves a targeted element into the file.
 *
 * @param target    element path
 * @param args      arguments (e.g. "name=outputfile|format=xml")
 */
Selenium.prototype.doSaveIntoFile = function(target, args) {

    args = args.split(";");

    for (i = 0 ; i < args.length ; i++) {
        
        var arg = args[i].split("=");

        args[arg[0]] = arg[1];

        //item.setAttribute(attr[0], attr[1]);
    }

    var element = this.browserbot.findElement(target);

    //alert(element.innerHTML);

    /*
     * Creating of DOM tree
     */

    var domTree = document.implementation.createDocument("", "", null);

    domTree.appendChild(element);

    /*
     * Saving into the file.
     */

    var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
                     .createInstance(Components.interfaces.nsIDOMSerializer);

    //var xml = serializer.serializeToString(xmlDoc);

    var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                   .createInstance(Components.interfaces.nsIFileOutputStream);

    var file = Components.classes["@mozilla.org/file/directory_service;1"]
               .getService(Components.interfaces.nsIProperties)
               .get("Home", Components.interfaces.nsIFile);                     // get home folder
    //file.append("extensions");                                                  // sub-directory

    if (!args['name']) {
        args['name'] = "output";
    }

    file.append(args['name'] + ".xml");                                         // filename

    var wayOfInit = 0x02 | 0x08 | 0x20;                                         // create file

    if (file.exists()) {
        wayOfInit = 0x02 | 0x10;                                                // append only
    }

    foStream.init(file, wayOfInit, 0644, 0);

    serializer.serializeToStream(domTree, foStream, "");                         // rememeber, xmlDoc is the DOM tree

    foStream.close();
}

Selenium.prototype.doShowStoredVars = function(target, args) {
    alert(storedVars['ahoj']);
}

/**
 * Rewrites original <code>locateElementByXPath<code> function.
 */
Recorder.prototype.attach = function() {
    this.log.debug("attaching");
    this.locatorBuilders = new LocatorBuilders(this.window);

    /* ********** REWRITE START ********** */
    this.locatorBuilders.pageBot = function() {
        var pageBot = this.window._locator_pageBot;
        if (pageBot == null) {
            //pageBot = BrowserBot.createForWindow(this.window);
            pageBot = new MozillaBrowserBot(this.window);
            /* ********** REWRITE START ********** */
            pageBot.locateElementByXPath = function(xpath, inDocument, inWindow) {
                var results = eval_xpath(xpath, inDocument, {
                    returnOnFirstMatch          : true,
                    ignoreAttributesWithoutValue: this.ignoreAttributesWithoutValue,
                    allowNativeXpath            : this.allowNativeXpath,
                    xpathLibrary                : this.xpathLibrary,
                    namespaceResolver           : this._namespaceResolver
                });
                //return (results.length > 0) ? results[0] : null;
                return (results.length > 0) ? results : null;
            };

            pageBot.locationStrategies['xpath'] = pageBot.locateElementByXPath;

            pageBot.locationStrategies['implicit'] = function(locator, inDocument, inWindow) {
                if (locator.startsWith('//')) {
                    /* ********** REWRITE START ********** */
                    var results = this.locateElementByXPath(locator, inDocument, inWindow);
                    
                    return (results.length > 0) ? results[0] : null;
                    /* ********** REWRITE END ********** */
                }
                if (locator.startsWith('document.')) {
                    return this.locateElementByDomTraversal(locator, inDocument, inWindow);
                }
                return this.locateElementByIdentifier(locator, inDocument, inWindow);
            };
            /* ********** REWRITE END ********** */
            var self = this;

            pageBot.getCurrentWindow = function() {
                return self.window;
            }

            this.window._locator_pageBot = pageBot;
        }

        return pageBot;
    }
    /* ********** REWRITE END ********** */

    this.eventListeners = {};
    this.reattachWindowMethods();
    var self = this;
    for (eventKey in Recorder.eventHandlers) {
        var eventInfo = this.parseEventKey(eventKey);
        var eventName = eventInfo.eventName;
        var capture = eventInfo.capture;
        // create new function so that the variables have new scope.
        function register() {
            var handlers = Recorder.eventHandlers[eventKey];
            //this.log.debug('eventName=' + eventName + ' / handlers.length=' + handlers.length);
            var listener = function(event) {
                self.log.debug('listener: event.type=' + event.type + ', target=' + event.target);
                //self.log.debug('title=' + self.window.document.title);
                var recording = false;
                for (var i = 0; i < self.observers.length; i++) {
                    if (self.observers[i].recordingEnabled) recording = true;
                }
                for (var i = 0; i < handlers.length; i++) {
                    if (recording || handlers[i].alwaysRecord) {
                        handlers[i].call(self, event);
                    }
                }
            }
            this.window.document.addEventListener(eventName, listener, capture);
            this.eventListeners[eventKey] = listener;
        }
        register.call(this);
    }
}

/**
 * Rewrites original <code>locateElementByXPath<code> function.
 */
Selenium.createForWindow = function(window, proxyInjectionMode) {
    if (!window.location) {
        throw "error: not a window!";
    }

    var selenium = new Selenium(BrowserBot.createForWindow(window, proxyInjectionMode));
    /* ********** REWRITE START ********** */
    selenium.browserbot.locateElementByXPath = function(xpath, inDocument, inWindow) {
        var results = eval_xpath(xpath, inDocument, {
            returnOnFirstMatch          : true,
            ignoreAttributesWithoutValue: this.ignoreAttributesWithoutValue,
            allowNativeXpath            : this.allowNativeXpath,
            xpathLibrary                : this.xpathLibrary,
            namespaceResolver           : this._namespaceResolver
        });
        //return (results.length > 0) ? results[0] : null;
        return (results.length > 0) ? results : null;
    };

    selenium.browserbot.locationStrategies['xpath'] = selenium.browserbot.locateElementByXPath;
    
    selenium.browserbot.locationStrategies['implicit'] = function(locator, inDocument, inWindow) {
        if (locator.startsWith('//')) {
            /* ********** REWRITE START ********** */
            var results = this.locateElementByXPath(locator, inDocument, inWindow);

            return (results.length > 0) ? results[0] : null;
            /* ********** REWRITE END ********** */
        }
        if (locator.startsWith('document.')) {
            return this.locateElementByDomTraversal(locator, inDocument, inWindow);
        }
        return this.locateElementByIdentifier(locator, inDocument, inWindow);
    };
    /* ********** REWRITE END ********** */
    return selenium;
};